package ru.hh.team02.chat.messaging;

import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import ru.hh.team02.chat.client.Client;
import ru.hh.team02.chat.server.Services;

/**
 * class responsible for macro sending logic. current version - one queue with
 * messages per active client
 */
public class SendingService {

    /**
     * send personal message
     * @param message - message text
     * @param recipientName
     */
    public void SendPersonalMessage(final String message, final String recipientName, final String senderName) {
        if (!Services.dbService.clientExists(recipientName)) {
            Client recipient = Services.REGISTRY.getClientByName(senderName);
            recipient.add(new NormalMessage("server> you are trying to communicate with unknown client"));

            Services.ADMIN_LOGGER.write("Client \"" + senderName
                    + "\" tried to communicate with unknown client");

            return;
        }

        if (Services.REGISTRY.hasClientWithName(recipientName)) {
            // super async stuff
            FutureTask<Integer> id = new FutureTask<Integer>(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    return Services.dbService.putNewPersonalMessageIntoDatabase(message, recipientName);
                }
            });
            new Thread(id).start();


            Client recipient = Services.REGISTRY.getClientByName(recipientName);
            recipient.add(new AsyncPrivateMessage(message, id));
            Services.ADMIN_LOGGER.write("Client \"" + senderName
                    + "\" sent new message: \""
                    + message + "\" to \"" + recipientName + "\"");
        }

    }


    /**
     * Send all undelivered messages to the recipient which will be taken from the DB.
     * @param recipientName Recipient name
     */
    public void sendUndeliveredMessages(String recipientName) {
        List<PrivateMessage> messages = Services.dbService.getAllUndeliveredMessagesToTheClient(recipientName);

        if (Services.REGISTRY.hasClientWithName(recipientName)) {
            Client recipient = Services.REGISTRY.getClientByName(recipientName);
            // XXX [Oleg] We should use there analog of addAll (e.g. AddAllToFront) to make it in one blocking
            for (PrivateMessage entry : messages) {
                recipient.add(entry);
            }
        }
    }

    /**
     * Send server message
     * @param message Message text
     * @param recipientName Recipient name
     */
    public void sendServiceMessage(String message, String recipientName) {
        if (Services.REGISTRY.hasClientWithName(recipientName)) {
            Client recipient = Services.REGISTRY.getClientByName(recipientName);
            recipient.add(new NormalMessage(message));
        }
    }

    /**
     * Put message to all personal queues of people, who are in the same room as
     * sender
     *
     * @param text
     *            Message text
     * @param senderName
     *            Sender name
     */
    // XXX [Oleg] Why do we need here senderName, and the other methods don't have this parameter.
    // XXX [Oleg] This inconsistency is very noticeable and unpleasant. It is justified?
    public void sendMessageToRoom(String text, String senderName) {
        String room = Services.REGISTRY.getClientRoom(senderName);
        Set<Client> recipients = Services.REGISTRY.getClientsFromRoom(room);

        for (Client recipient : recipients) {
            recipient.add(new NormalMessage(text));
        }

    }
}
